﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Management.Automation;
using Microsoft.Health;
using Microsoft.Health.ItemTypes;
using System.IO;
using System.Configuration;
using System.Xml;
using System.Xml.XPath;

namespace HealthVaultPowerShell
{
    #region Authorization Commands

    [Cmdlet("Grant", "Access")]
    public class GrantAccessCommand : PSCmdlet
    {
        private Guid powerShellGuid = new Guid("e43d65c4-52e2-4da2-8ee0-9cf508472370");
        private Uri platformUrl = new Uri("https://platform.healthvault-ppe.com/platform/");
        private Uri shellUrl = new Uri("https://account.healthvault-ppe.com/");
        private bool yes, no;
     
        protected override void ProcessRecord()
        {
            HealthClientApplication clientApp = HealthClientApplication.Create(
                Guid.NewGuid(), powerShellGuid, shellUrl, platformUrl);

            var healthVaultUtil = SingleTonHealthVaultShellUtilities.HealthVaultShellUtilInstance;    
          
            if (clientApp.GetApplicationInfo() == null)
            {
                clientApp.StartApplicationCreationProcess();
                if (ShouldContinue("Is Authentication done - (Y)?", "Is auth done?", ref yes, ref no))
                {
                    var data = new StringBuilder();
                    data.Append(clientApp.ApplicationId.ToString());
                    using (var sw = new StreamWriter(healthVaultUtil.GetClientAppAuthFileNameFullPath()))
                    {
                        sw.Write((data));
                    }
                    var authorizedPeople = new List<PersonInfo>(clientApp.ApplicationConnection.GetAuthorizedPeople());
                    if (authorizedPeople.Count > 0)
                        WriteObject(authorizedPeople);
                    else
                        WriteObject("No authorized peoples found");
                }
            }
        }        
    }

    [Cmdlet("Remove", "Access")]
    public class RemoveAccessCommand : PSCmdlet
    {      
        protected override void ProcessRecord()
        {
            // remove authorization of application from server
            var healthVaultUtil = SingleTonHealthVaultShellUtilities.HealthVaultShellUtilInstance;
            HealthClientApplication clientApp = healthVaultUtil.GetClient();

            if (clientApp.GetApplicationInfo() != null)
            {

                var authorizedPeople = new List<PersonInfo>(clientApp.ApplicationConnection.GetAuthorizedPeople());
                if (authorizedPeople.Count == 0) {
                    WriteObject("No authorized peoples found");
                    return;
                }
                 
                HealthClientAuthorizedConnection authConnection = clientApp.CreateAuthorizedConnection(
                authorizedPeople[0].PersonId);

                HealthRecordAccessor accessor = new HealthRecordAccessor(authConnection, authConnection.GetPersonInfo().GetSelfRecord().Id);
                accessor.RemoveApplicationAuthorization();
                WriteDebug("Successfull removal of Authorization to HealthVault");
            }                    
        }
    }

    #endregion

    #region Get/Fetch Commands

    [Cmdlet("Get", "Personinfo")]
    public class GetPersonInfo : PSCmdlet
    {
        protected override void ProcessRecord()
        {
            var healthVaultUtil = SingleTonHealthVaultShellUtilities.HealthVaultShellUtilInstance;
            HealthClientApplication clientApp = healthVaultUtil.GetClient();
            if (clientApp.GetApplicationInfo() != null)
            {
                var authorizedPeople = new List<PersonInfo>(clientApp.ApplicationConnection.GetAuthorizedPeople());
                if (authorizedPeople.Count > 0)
                    WriteObject(authorizedPeople);
                else
                    WriteObject("No authorized peoples found");
            }
        }
    }

    [Cmdlet("Get", "Things")]
    public class GetThing : PSCmdlet
    {
        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty]
        public string ParameterName
        {
            get;
            set;
        }

        protected override void ProcessRecord()
        {
            var healthVaultUtil = SingleTonHealthVaultShellUtilities.HealthVaultShellUtilInstance;
            HealthClientApplication clientApp = healthVaultUtil.GetClient();

            List<PersonInfo> authorizedPeople = new List<PersonInfo>(clientApp.ApplicationConnection.GetAuthorizedPeople());
            if (authorizedPeople.Count == 0)
            {
                WriteObject("No authorized peoples found");
                return;
            }
            HealthClientAuthorizedConnection authConnection = clientApp.CreateAuthorizedConnection(authorizedPeople[0].PersonId);
            
            HealthRecordAccessor access = new HealthRecordAccessor(authConnection, authConnection.GetPersonInfo().GetSelfRecord().Id);
            HealthRecordSearcher search = access.CreateSearcher();
            HealthRecordFilter filter = new HealthRecordFilter(healthVaultUtil.NameToTypeId(ParameterName));
            
            search.Filters.Add(filter);
            foreach (var o in search.GetMatchingItems()[0])
            {
                WriteObject(o);
            }
        }
    }

    [Cmdlet("Get", "PersonImage")]
    public class GetPersonImage : PSCmdlet
    {
        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty]
        public string ImagePath
        {
            get;
            set;
        }

        protected override void ProcessRecord()
        {
            var healthVaultUtil = SingleTonHealthVaultShellUtilities.HealthVaultShellUtilInstance;
            HealthClientApplication clientApp = healthVaultUtil.GetClient();
            var authorizedPeople = new List<PersonInfo>(clientApp.ApplicationConnection.GetAuthorizedPeople());

            if (authorizedPeople.Count == 0)
            {
                WriteObject("No authorized peoples found");
                return;
            }

            HealthClientAuthorizedConnection connection = clientApp.CreateAuthorizedConnection(authorizedPeople[0].PersonId);
            HealthRecordAccessor accessor = new HealthRecordAccessor(connection, authorizedPeople[0].SelectedRecord.Id);
            var personInfo = connection.GetPersonInfo();

            if (personInfo.SelectedRecord == null)
                throw new Exception("Default person record has not found");

            if (!System.IO.File.Exists(ImagePath))
            {
                var file = System.IO.File.Create(ImagePath);
                file.Close();
            }

            HealthRecordItemCollection collection = personInfo.SelectedRecord.GetItemsByType(PersonalImage.TypeId, HealthRecordItemSections.All);
            PersonalImage image = null;

            if (collection.Count != 0)
            {
                image = collection[0] as PersonalImage;
                using (var currentImageStream = image.ReadImage())
                {
                    byte[] imageBytes = new byte[currentImageStream.Length];
                    currentImageStream.Read(imageBytes, 0, (int)currentImageStream.Length);
                    System.IO.File.WriteAllBytes(ImagePath, imageBytes);
                }
            } 
        }
    }

    #endregion

    #region Put/Upload Commands

    [Cmdlet("Upload", "Labresults")]
    public class UploadLabResults : PSCmdlet
    {
        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty]
        public string LabResultPath
        {
            get;
            set;
        }

        [Parameter(Position = 1)]
        [ValidateNotNullOrEmpty]
        public string LabResultSource
        {
            get;
            set;
        }

        protected override void ProcessRecord()
        {
              string labResultXpath = "lab-test-results/data-xml/lab-test-results";
              string extensionXpath = "lab-test-results/data-xml/common/additional-labgroup-data";
              XmlDocument xmldocument = new XmlDocument();
              xmldocument.Load(LabResultPath);

              XmlDocument labDoc = new XmlDocument();
              labDoc.LoadXml(xmldocument.SelectSingleNode(labResultXpath).OuterXml);
              XPathNavigator navigator = xmldocument.CreateNavigator();

              var healthVaultUtil = SingleTonHealthVaultShellUtilities.HealthVaultShellUtilInstance;
              HealthClientApplication clientApp = healthVaultUtil.GetClient();
              var authorizedPeople = new List<PersonInfo>();
              if (clientApp.GetApplicationInfo() != null)
              {
                  authorizedPeople = new List<PersonInfo>(clientApp.ApplicationConnection.GetAuthorizedPeople());
                  if (authorizedPeople.Count == 0)
                  {
                      WriteObject("No authorized peoples found");
                      return;
                  }
              }
                 
              HealthClientAuthorizedConnection authConnection = clientApp.CreateAuthorizedConnection(authorizedPeople[0].PersonId);
              HealthRecordAccessor accessor = new HealthRecordAccessor(authConnection, authConnection.GetPersonInfo().GetSelfRecord().Id);
              HealthRecordItem labItem = new HealthRecordItem(healthVaultUtil.NameToTypeId("labResult"), labDoc);

              HealthRecordItemExtension extension = new HealthRecordItemExtension(LabResultSource);
              labItem.CommonData.Extensions.Add(extension);
              XPathNavigator extensionNavigator = extension.ExtensionData.CreateNavigator();
              extensionNavigator.InnerXml = navigator.SelectSingleNode(extensionXpath).InnerXml;

              // Add new LabItem
              accessor.NewItem(labItem);
          }
    }

    [Cmdlet("Upload", "Document")]
    public class UploadClinicalDocument : PSCmdlet
    {
        [Parameter(Position = 0)]
        [ValidateNotNullOrEmpty]
        public string DocumentPath
        {
            get;
            set;
        }

        [Parameter(Position = 1)]
        [ValidateNotNullOrEmpty]
        public string DocumentType
        {
            get;
            set;
        }          

        protected override void ProcessRecord()
        {
            var healthVaultUtil = SingleTonHealthVaultShellUtilities.HealthVaultShellUtilInstance;
            HealthClientApplication clientApp = healthVaultUtil.GetClient();
            var authorizedPeople = new List<PersonInfo>();
            if (clientApp.GetApplicationInfo() != null)
            {
                authorizedPeople = new List<PersonInfo>(clientApp.ApplicationConnection.GetAuthorizedPeople());
                if (authorizedPeople.Count == 0)
                {
                    WriteObject("No authorized peoples found");
                    return;
                }
            }

            HealthClientAuthorizedConnection authConnection = clientApp.CreateAuthorizedConnection(authorizedPeople[0].PersonId);
            HealthRecordAccessor accessor = new HealthRecordAccessor(authConnection, authConnection.GetPersonInfo().GetSelfRecord().Id);

            Guid itemTypeGuid = Guid.Empty;
            if(DocumentType.Equals("ccd"))
                itemTypeGuid = healthVaultUtil.NameToTypeId("ccd");
            else
            if (DocumentType.Equals("ccr"))
                itemTypeGuid = healthVaultUtil.NameToTypeId("ccr");
            else
            {
                WriteObject("Document type not supported");
                return;
            }
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(DocumentPath);

            if (xmlDocument.ChildNodes.Count == 0)
            {
                WriteObject("No clinical information found in the clinical document");
                return;
            }
            accessor.NewItem(new HealthRecordItem(itemTypeGuid, xmlDocument));
        }
    }

    #endregion
}
